namespace Creek.UI.EFML.Base.Controls.Navigator
{
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Reflection;
    using System.Windows.Forms;

    using global::EFML.Properties;

    #region TravelButton

    [DefaultEvent("ItemClicked")]
    public partial class TravelButton : Control
    {
        #region Fields

        private readonly Rectangle BACKGROUND_RECT = new Rectangle(0, 0, 74, 29);

        private readonly Rectangle BACK_BUTTON_RECT = new Rectangle(2, 2, 25, 25);

        private readonly Rectangle DROPDOWN_ARROW_RECT = new Rectangle(57, 4, 17, 20);

        private readonly Rectangle FORWARD_BUTTON_RECT = new Rectangle(30, 2, 25, 25);

        private bool _bButtonEnabled = true;

        private bool _bButtonOnly;

        private ControlState _bButtonState = ControlState.Normal;

        private string _bToolTip;

        private Image _backButton;

        private Image _backGround;

        private ControlState _ddArrowState = ControlState.Normal;

        private ContextMenuStrip _dropDownMenu;

        private bool _fButtonEnabled = true;

        private ControlState _fButtonState = ControlState.Normal;

        private string _fToolTip;

        private Image _forwardButton;

        private bool _showMenu = true;

        #endregion

        #region Constructors and Destructors

        public TravelButton()
        {
            Assembly assembly = Assembly.GetAssembly(typeof(TravelButton));

            this._backGround = Resources.BACKGROUND_arrowless;
            this._backButton = Resources.LEFTBUTTON;
            this._forwardButton = Resources.RIGHTBUTTON;

            this.DoubleBuffered = true;

            this.InitializeComponent();
        }

        #endregion

        #region Public Events

        [Browsable(false)]
        public event EventHandler DropDownMenuChanged;

        [Browsable(true)]
        public event TravelButtonItemClickedEventHandler ItemClicked;

        [Browsable(false)]
        public event PaintEventHandler PaintBackground;

        #endregion

        #region Enums

        private enum ControlState
        {
            Normal,

            Hover,

            Pressed,

            Disabled
        }

        #endregion

        #region Public Properties

        [Category("Behavior")]
        [Browsable(true)]
        [DefaultValue(false)]
        public bool BackButtonOnly
        {
            get
            {
                return this._bButtonOnly;
            }
            set
            {
                this._bButtonOnly = value;
                if (this._bButtonOnly)
                {
                    this._fButtonEnabled = false;
                }

                this.Invalidate();
            }
        }

        [Category("Behavior")]
        [Browsable(true)]
        [DefaultValue(true)]
        public bool BackEnabled
        {
            get
            {
                return this._bButtonEnabled;
            }
            set
            {
                this._bButtonEnabled = value;
                this.Invalidate();
            }
        }

        public Image BackGround
        {
            get
            {
                return this._backGround;
            }
            set
            {
                this._backGround = value;
            }
        }

        [Browsable(true)]
        public string BackToolTip
        {
            get
            {
                return this._bToolTip;
            }
            set
            {
                this._bToolTip = value;
            }
        }

        public Image BackwardButton
        {
            get
            {
                return this._backButton;
            }
            set
            {
                this._backButton = value;
            }
        }

        [Category("Behavior")]
        [Browsable(true)]
        [DefaultValue(null)]
        public ContextMenuStrip DropDownMenu
        {
            get
            {
                return this._dropDownMenu;
            }
            set
            {
                if (!this.DesignMode && this._dropDownMenu != null)
                {
                    this._dropDownMenu.VisibleChanged -= this.DropDownMenu_VisibleChanged;
                }

                this._dropDownMenu = value;

                if (!this.DesignMode && this._dropDownMenu != null)
                {
                    this._dropDownMenu.VisibleChanged += this.DropDownMenu_VisibleChanged;
                }

                if (this.DropDownMenuChanged != null)
                {
                    this.DropDownMenuChanged(this, EventArgs.Empty);
                }
            }
        }

        public Image ForwardButton
        {
            get
            {
                return this._forwardButton;
            }
            set
            {
                this._forwardButton = value;
            }
        }

        [Category("Behavior")]
        [Browsable(true)]
        [DefaultValue(true)]
        public bool ForwardEnabled
        {
            get
            {
                return (!this._bButtonOnly && this._fButtonEnabled);
            }
            set
            {
                this._fButtonEnabled = (!this._bButtonOnly && value);
                this.Invalidate();
            }
        }

        [Browsable(true)]
        public string ForwardToolTip
        {
            get
            {
                return this._fToolTip;
            }
            set
            {
                this._fToolTip = value;
            }
        }

        #endregion

        #region Properties

        private bool DDArrowEnabled
        {
            get
            {
                return (!this._bButtonOnly && (this.BackEnabled || this.ForwardEnabled) && this._dropDownMenu != null
                        && this._dropDownMenu.Items.Count != 0);
            }
        }

        #endregion

        #region Public Methods and Operators

        public void SetButtonEnabled(TravelButtonItem item, bool enable)
        {
            if (item == TravelButtonItem.BackButton)
            {
                this.BackEnabled = enable;
            }
            else if (item == TravelButtonItem.ForwardButton)
            {
                this.ForwardEnabled = enable;
            }
        }

        public void SetButtonToolTip(TravelButtonItem item, string tip)
        {
            if (item == TravelButtonItem.BackButton)
            {
                this.BackToolTip = tip;
            }
            else if (item == TravelButtonItem.ForwardButton)
            {
                this.ForwardToolTip = tip;
            }
        }

        #endregion

        #region Methods

        protected override void OnClick(EventArgs e)
        {
            if (this.Enabled)
            {
                Point p = this.PointToClient(MousePosition);
                var item = TravelButtonItem.BackGround;

                if (this.BackEnabled && this.BACK_BUTTON_RECT.Contains(p.X, p.Y))
                {
                    item = TravelButtonItem.BackButton;
                    this._bButtonState = ControlState.Hover;
                }
                else if (!this.BackButtonOnly && this.ForwardEnabled && this.FORWARD_BUTTON_RECT.Contains(p.X, p.Y))
                {
                    item = TravelButtonItem.ForwardButton;
                    this._fButtonState = ControlState.Hover;
                }
                else if (!this.BackButtonOnly && this.DDArrowEnabled && this.DROPDOWN_ARROW_RECT.Contains(p.X, p.Y))
                {
                    item = TravelButtonItem.DropDownArrow;
                    //_dropDownArrowState = ControlState.Hover;
                }

                this.Invalidate();

                if (item != TravelButtonItem.BackGround && this.ItemClicked != null)
                {
                    this.ItemClicked(this, new TravelButtonItemClickedEventArgs(item));
                }
            }

            base.OnClick(e);
        }

        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);
            this.Invalidate();
        }

        protected override void OnMouseDoubleClick(MouseEventArgs me)
        {
            if (this.DROPDOWN_ARROW_RECT.Contains(me.X, me.Y))
            {
                return;
            }
            else
            {
                base.OnMouseDoubleClick(me);
            }
        }

        protected override void OnMouseDown(MouseEventArgs me)
        {
            base.OnMouseDown(me);

            if (this.Enabled)
            {
                if (me.Button == MouseButtons.Left && me.Clicks == 1)
                {
                    if (this.BackEnabled && this.BACK_BUTTON_RECT.Contains(me.X, me.Y))
                    {
                        this._bButtonState = ControlState.Pressed;
                        this._fButtonState = ControlState.Normal;
                        this._ddArrowState = ControlState.Normal;
                        this._showMenu = true;
                    }
                    else if (!this.BackButtonOnly && this.ForwardEnabled && this.FORWARD_BUTTON_RECT.Contains(me.X, me.Y))
                    {
                        this._bButtonState = ControlState.Normal;
                        this._fButtonState = ControlState.Pressed;
                        this._ddArrowState = ControlState.Normal;
                        this._showMenu = true;
                    }
                    else if (!this.BackButtonOnly && this.DDArrowEnabled
                             && this.DROPDOWN_ARROW_RECT.Contains(me.X, me.Y))
                    {
                        this._bButtonState = ControlState.Normal;
                        this._fButtonState = ControlState.Normal;

                        if (this._dropDownMenu != null)
                        {
                            if (this._showMenu)
                            {
                                this._dropDownMenu.Show(
                                    this,
                                    new Point(this.BACKGROUND_RECT.X, this.BACKGROUND_RECT.Height),
                                    ToolStripDropDownDirection.Default);
                                this._ddArrowState = ControlState.Pressed;
                            }
                            else
                            {
                                this._ddArrowState = ControlState.Hover;
                            }
                            this._showMenu = !this._showMenu;
                        }
                        else
                        {
                            this._ddArrowState = ControlState.Hover;
                            this._showMenu = true;
                        }
                    }
                    else
                    {
                        this._bButtonState = ControlState.Normal;
                        this._fButtonState = ControlState.Normal;
                        this._ddArrowState = ControlState.Normal;
                        this._showMenu = true;
                    }

                    this.Invalidate();
                }
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);

            this._bButtonState = ControlState.Normal;
            this._fButtonState = ControlState.Normal;

            if (this._dropDownMenu != null && this._dropDownMenu.Visible)
            {
                this._ddArrowState = ControlState.Pressed;
            }
            else
            {
                this._ddArrowState = ControlState.Normal;
            }

            this.Invalidate();

            this._showMenu = true;
        }

        protected override void OnMouseMove(MouseEventArgs me)
        {
            base.OnMouseMove(me);

            if (this.Enabled && !this.Capture)
            {
                if (this.BackEnabled && this.BACK_BUTTON_RECT.Contains(me.X, me.Y))
                {
                    this._bButtonState = ControlState.Hover;
                    this._fButtonState = ControlState.Normal;
                    this._ddArrowState = ControlState.Normal;

                    this.SetToolTip(TravelButtonItem.BackButton);
                }
                else if (!this.BackButtonOnly && this.ForwardEnabled && this.FORWARD_BUTTON_RECT.Contains(me.X, me.Y))
                {
                    this._bButtonState = ControlState.Normal;
                    this._fButtonState = ControlState.Hover;
                    this._ddArrowState = ControlState.Normal;

                    this.SetToolTip(TravelButtonItem.ForwardButton);
                }
                else if (!this.BackButtonOnly && this.DDArrowEnabled && this.DROPDOWN_ARROW_RECT.Contains(me.X, me.Y))
                {
                    this._bButtonState = ControlState.Normal;
                    this._fButtonState = ControlState.Normal;
                    this._ddArrowState = ControlState.Hover;

                    this.SetToolTip(TravelButtonItem.DropDownArrow);
                }
                else
                {
                    this._bButtonState = ControlState.Normal;
                    this._fButtonState = ControlState.Normal;
                    this._ddArrowState = ControlState.Normal;

                    this.SetToolTip(TravelButtonItem.BackGround);
                }

                this.Invalidate();
            }
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            if (this.Enabled)
            {
                if (!this.BackButtonOnly)
                {
                    if (this.DDArrowEnabled)
                    {
                        this.DrawItem(pe.Graphics, TravelButtonItem.BackGround, this._ddArrowState);
                    }
                    else
                    {
                        this.DrawItem(pe.Graphics, TravelButtonItem.BackGround, ControlState.Disabled);
                    }
                }
                else
                {
                    this.DrawItem(pe.Graphics, TravelButtonItem.BackGround, ControlState.Disabled);
                }

                if (this.BackEnabled)
                {
                    this.DrawItem(pe.Graphics, TravelButtonItem.BackButton, this._bButtonState);
                }
                else
                {
                    this.DrawItem(pe.Graphics, TravelButtonItem.BackButton, ControlState.Disabled);
                }

                if (!this.BackButtonOnly)
                {
                    if (this.ForwardEnabled)
                    {
                        this.DrawItem(pe.Graphics, TravelButtonItem.ForwardButton, this._fButtonState);
                    }
                    else
                    {
                        this.DrawItem(pe.Graphics, TravelButtonItem.ForwardButton, ControlState.Disabled);
                    }
                }
            }
            else
            {
                this.DrawItem(pe.Graphics, TravelButtonItem.BackGround, ControlState.Disabled);
                this.DrawItem(pe.Graphics, TravelButtonItem.BackButton, ControlState.Disabled);

                if (!this.BackButtonOnly)
                {
                    this.DrawItem(pe.Graphics, TravelButtonItem.ForwardButton, ControlState.Disabled);
                }
            }

            base.OnPaint(pe);
        }

        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            if (this.PaintBackground != null)
            {
                this.PaintBackground(this, pevent);
            }
            else
            {
                base.OnPaintBackground(pevent);
            }
        }

        private void DrawItem(Graphics g, TravelButtonItem item, ControlState state)
        {
            Rectangle srcRect;
            switch (item)
            {
                case TravelButtonItem.BackButton:
                    srcRect = new Rectangle(new Point(0, 0), this.BACK_BUTTON_RECT.Size);
                    break;
                case TravelButtonItem.ForwardButton:
                    srcRect = new Rectangle(new Point(0, 0), this.FORWARD_BUTTON_RECT.Size);
                    break;
                default:
                    srcRect = this.BACKGROUND_RECT;
                    break;
            }

            int xOffset = 0;
            switch (state)
            {
                case ControlState.Normal:
                    xOffset = 0;
                    break;
                case ControlState.Pressed:
                    xOffset = srcRect.Width;
                    break;
                case ControlState.Hover:
                    xOffset = srcRect.Width * 2;
                    break;
                case ControlState.Disabled:
                    xOffset = srcRect.Width * 3;
                    break;
            }

            srcRect.X = xOffset;

            if (item == TravelButtonItem.BackButton)
            {
                g.DrawImage(this._backButton, this.BACK_BUTTON_RECT, srcRect, GraphicsUnit.Pixel);
            }
            else if (item == TravelButtonItem.ForwardButton)
            {
                g.DrawImage(this._forwardButton, this.FORWARD_BUTTON_RECT, srcRect, GraphicsUnit.Pixel);
            }
            else if (item == TravelButtonItem.BackGround)
            {
                if (!this.BackButtonOnly)
                {
                    g.DrawImage(this._backGround, this.BACKGROUND_RECT, srcRect, GraphicsUnit.Pixel);
                }
                else
                {
                    var rect1 = new Rectangle(
                        this.BACKGROUND_RECT.X,
                        this.BACKGROUND_RECT.Y,
                        this.BACKGROUND_RECT.Width - this.DROPDOWN_ARROW_RECT.Width,
                        this.BACKGROUND_RECT.Height);
                    var rect2 = new Rectangle(
                        srcRect.X, srcRect.Y, srcRect.Width - this.DROPDOWN_ARROW_RECT.Width, srcRect.Height);
                    g.DrawImage(this._backGround, rect1, rect2, GraphicsUnit.Pixel);
                }
            }
        }

        private void DropDownMenu_VisibleChanged(object sender, EventArgs e)
        {
            var menu = sender as ContextMenuStrip;
            if (menu != null)
            {
                if (!menu.Visible)
                {
                    this._ddArrowState = ControlState.Normal;
                }

                this.Invalidate();
            }
        }

        private void SetToolTip(TravelButtonItem item)
        {
            string curToolTip = this.toolTip.GetToolTip(this);

            if (item == TravelButtonItem.BackButton)
            {
                if (curToolTip != this._bToolTip)
                {
                    this.toolTip.SetToolTip(this, this._bToolTip);
                }
            }
            else if (item == TravelButtonItem.ForwardButton)
            {
                if (curToolTip != this._fToolTip)
                {
                    this.toolTip.SetToolTip(this, this._fToolTip);
                }
            }
            else
            {
                this.toolTip.Hide(this);
            }
        }

        #endregion
    }

    #endregion

    #region Other

    public delegate void TravelButtonItemClickedEventHandler(object sender, TravelButtonItemClickedEventArgs e);

    public enum TravelButtonItem
    {
        BackGround,

        BackButton,

        ForwardButton,

        DropDownArrow
    }

    public class TravelButtonItemClickedEventArgs : EventArgs
    {
        #region Fields

        private readonly TravelButtonItem _item = TravelButtonItem.BackGround;

        #endregion

        #region Constructors and Destructors

        public TravelButtonItemClickedEventArgs(TravelButtonItem clickedItem)
        {
            this._item = clickedItem;
        }

        #endregion

        #region Public Properties

        public TravelButtonItem ClickedItem
        {
            get
            {
                return this._item;
            }
        }

        #endregion
    }

    #endregion
}